#include "type.h"
#include "const.h"
#include "protect.h"
#include "proto.h"
#include "string.h"
#include "proc.h"
#include "global.h"

public int kernel_main()
{
    // sub esp, 12
    // push  0x00032310
    // call disp_str
    // add esp, 16
    disp_str("----\"kernel_main\" begins-----\n");
    
    Task* p_task = task_table;
    Process* p_proc = proc_table;
    char * p_task_stack = task_stack + STACK_SIZE_TOTAL;

    u16 selector_ldt = SELECTOR_LDT_FIRST;
    int i = 0;
    for (i = 0; i < NR_TASKS; i++)
    {
        strcpy(p_proc->p_name, p_task->name);
        p_proc->pid = i;
        p_proc->ldt_sel = selector_ldt;

        memcpy(&p_proc->ldts[0], &gdt[SELECTOR_KERNEL_CS >> 3],
            sizeof(Descriptor));
        p_proc->ldts[0].attr1 = DA_C | PRIVILEGE_TASK << 5;
        memcpy(&p_proc->ldts[1], &gdt[SELECTOR_KERNEL_DS >> 3],
            sizeof(Descriptor));
        p_proc->ldts[1].attr1 = DA_DRW | PRIVILEGE_TASK << 5;

        p_proc->regs.cs = ((8 * 0) & SA_RPL_MASK & SA_TI_MASK)
            | SA_TIL | RPL_TASK;
        p_proc->regs.ds = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK)
            | SA_TIL | RPL_TASK;
        p_proc->regs.es = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK)
            | SA_TIL | RPL_TASK;
        p_proc->regs.fs = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK)
            | SA_TIL | RPL_TASK;
        p_proc->regs.ss = ((8 * 1) & SA_RPL_MASK & SA_TI_MASK)
            | SA_TIL | RPL_TASK;
        p_proc->regs.gs = (SELECTOR_KERNEL_GS & SA_RPL_MASK)
            | RPL_TASK;

        p_proc->regs.eip = (u32) p_task->initial_eip;
        p_proc->regs.esp = (u32) p_task_stack;
        p_proc->regs.eflags = 0x1202;

        p_task_stack -= (u32) p_task->stacksize;
        p_proc++;
        p_task++;
        selector_ldt += sizeof(Descriptor);
    }
    
    k_reenter = -1;

    // mov [ds:0x000354a0], 0x000354c0
    p_proc_ready = proc_table;
    restart();

    while (1)
    {
        
    }
    
}

void testA()
{
    int i = 0;
    while(1)
    {
        disp_str("A");
        disp_int(i++);
        disp_str(".");
        delay(1);
    }
}

void testB()
{
    int i = 0x1000;
    while (1)
    {
        disp_str("B");
        disp_int(i++);
        disp_str(".");
        delay(1);
    }
}